package io.r2mo.io.common;

import io.r2mo.base.io.HStore;
import io.r2mo.spi.SPI;
import io.r2mo.typed.cc.Cc;
import io.r2mo.typed.json.JArray;
import io.r2mo.typed.json.JBase;
import io.r2mo.typed.json.JObject;

import javax.crypto.SecretKey;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Path;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;

/**
 * 统一访问接口，用来完成和 IO 直接对接的部分，而 Zero 中实现的是异步模式的继承，来完成整体对接部分，替换原始的 HFS
 * 的 IO 操作
 *
 * @author lang : 2025-09-01
 */
public class HFS {
    private static final Cc<String, HFS> CCT_HFS = Cc.openThread();
    private final HStore store;

    protected HFS() {
        this.store = SPI.SPI_IO.ioAction();
    }

    public static HFS of() {
        return CCT_HFS.pick(HFS::new);
    }

    /* cp */
    public boolean cp(final String from, final String to) {
        return this.store.cp(from, to);
    }

    /* mv */
    public boolean mv(final String from, final String to) {
        return this.store.mv(from, to);
    }

    public boolean mv(final ConcurrentMap<String, String> vectorMap) {
        return this.store.mv(vectorMap);
    }

    /* mkdir -p */
    public boolean mkdir(final String dir) {
        return this.store.mkdir(dir);
    }

    public boolean mkdir(final Set<String> dirs) {
        return this.store.mkdir(dirs);
    }

    /* rm */
    public boolean rm(final String filename) {
        return this.store.rm(filename);
    }

    public boolean rm(final Set<String> filenames) {
        return this.store.rm(filenames);
    }

    /* ls */
    public List<String> lsFiles(final String filename, final String keyword) {
        return this.store.lsFiles(filename, keyword);
    }

    /* ls */
    public List<String> lsFilesN(final String filename, final String keyword) {
        return this.store.lsFilesN(filename, keyword);
    }

    public List<String> lsDirs(final String filename) {
        return this.store.lsDirs(filename);
    }

    public List<String> lsDirsN(final String filename) {
        return this.store.lsDirsN(filename);
    }

    /* 文件写入：echo */
    public boolean write(final String filename, final String content, final boolean append) {
        return this.store.write(filename, content, append);
    }

    public boolean write(final String filename, final InputStream in) {
        return this.store.write(filename, in);
    }

    public boolean write(final String filename, final PublicKey publicKey) {
        return this.store.write(filename, publicKey);
    }

    public boolean write(final String filename, final PrivateKey privateKey) {
        return this.store.write(filename, privateKey);
    }

    public boolean write(final String filename, final SecretKey secretKey) {
        return this.store.write(filename, secretKey);
    }

    // ------------------------------------ 判断专用方法
    public boolean isExist(final String path) {
        return this.store.isExist(path);
    }

    public boolean isDirectory(final String path) {
        return this.store.isDirectory(path);
    }

    public boolean isFile(final String path) {
        return this.store.isFile(path);
    }

    public boolean isEmpty(final String path) {
        return this.store.isEmpty(path);
    }

    public boolean isSame(final String path1, final String path2) {
        return this.store.isSame(path1, path2);
    }

    // ------------------------------------ 接口级方法
    public List<String> lsFiles(final String filename) {
        return this.lsFiles(filename, null);
    }

    public List<String> lsFilesN(final String filename) {
        return this.lsFiles(filename, null);
    }

    /* 文件读取 */
    public String inString(final String filename) {
        return this.store.inString(filename);
    }

    /**
     * 特殊接口，只局限于 {@link HFS} 中的调用流程，和 {@link HStore} 在这种 IO 模式会有所区别，{@link HStore} 主要
     * 是针对存储设备、存储介质进行抽象，而 {@link HFS} 相对比较具体，所以它提供了基于类路径 ClassPath 的部分操作，在接入
     * 本地环境时会比较方便。
     * 此接口加载流程
     * <pre>
     *     1. 优先考虑 {@link HStore} 之上的读取
     *     2. 其次尝试从 ClassPath 中读取
     * </pre>
     * 在类路径读取过程中，如果引入了 OSGI 的热部署环境，还可以传入第二参数 owner 来指定读取的 Bundle
     *
     * @param filename 文件名
     *
     * @return 内容
     */
    public String inContent(final String filename) {
        String content = null;
        if (this.isExist(filename)) {
            /* 文件已经存在，直接读取 */
            content = this.inString(filename);
        }
        if (Objects.isNull(content)) {
            /* 文件不存在或者没有读取到 */
            final URL urlPath = Thread.currentThread().getContextClassLoader().getResource(filename);
            content = this.inString(urlPath);
        }
        return content;
    }

    public String inString(final URL url) {
        return this.store.inString(url);
    }

    public byte[] inBytes(final String filename) {
        return this.store.inBytes(filename);
    }

    public byte[] inBytes(final URL url) {
        return this.store.inBytes(url);
    }

    /* 文件 Stream 读取 */
    public InputStream inStream(final String filename) {
        return this.store.inStream(filename);
    }

    public InputStream inStream(final URL url) {
        return this.store.inStream(url);
    }

    /* 读取 Properties */
    public Properties inProperties(final String filename) {
        return this.store.inProperties(filename);
    }

    public Properties inProperties(final URL url) {
        return this.store.inProperties(url);
    }

    public <T extends JBase> T inJson(final String filename) {
        return this.store.inJson(filename);
    }

    public <T extends JBase> T inJson(final URL url) {
        return this.store.inJson(url);
    }

    public <T extends JBase> T inYaml(final String filename) {
        return this.store.inYaml(filename);
    }

    public <T extends JBase> T inYaml(final URL url) {
        return this.store.inYaml(url);
    }

    public JObject ymlForJ(final String yamlString) {
        return this.store.ymlForJ(yamlString);
    }

    public JArray ymlForA(final String yamlString) {
        return this.store.ymlForA(yamlString);
    }

    // ---------------- 公私密钥读取
    public PublicKey inPublic(final String filename) {
        return this.store.inPublic(filename);
    }

    public PublicKey inPublic(final InputStream in) {
        return this.store.inPublic(in);
    }

    public PrivateKey inPrivate(final String filename) {
        return this.store.inPrivate(filename);
    }

    public PrivateKey inPrivate(final InputStream in) {
        return this.store.inPrivate(in);
    }

    public SecretKey inSecret(final String filename) {
        return this.store.inSecret(filename);
    }

    public SecretKey inSecret(final InputStream in) {
        return this.store.inSecret(in);
    }

    // ---------------- 下边方法不适合在网络或分布式环境中使用
    public String inString(final File file) {
        return this.store.inString(file);
    }

    public String inString(final Path file) {
        return this.store.inString(file);
    }

    public byte[] inBytes(final File file) {
        return this.store.inBytes(file);
    }

    public byte[] inBytes(final Path path) {
        return this.store.inBytes(path);
    }

    public InputStream inStream(final File file) {
        return this.store.inStream(file);
    }

    public InputStream inStream(final Path path) {
        return this.store.inStream(path);
    }

    public <T extends JBase> T inJson(final File file) {
        return this.store.inJson(file);
    }

    public <T extends JBase> T inJson(final Path path) {
        return this.store.inJson(path);
    }

    public <T extends JBase> T inYaml(final File file) {
        return this.store.inYaml(file);
    }

    public <T extends JBase> T inYaml(final Path path) {
        return this.store.inYaml(path);
    }

    public long fileSize(String path) {
        return this.store.fileSize(path);
    }
}
